package Data;

import java.sql.Connection;
import java.sql.SQLException;

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

/**
 * A class that handles the connection pooling of the DB. 
 */
public class ConnectionPool 
{
	private static final int retryCount = 3;
	
	private MysqlDataSource dataSource = null;
	private static ConnectionPool instance = null;
	
	/**
	 * Constructs the connection pool. It is private and used to instantiate the singleton.
	 * 
	 * @param serverUrl The URL of the DB server
	 * @param accountUser Username
	 * @param accountPassword Password
	 */
	private ConnectionPool(String serverUrl, String accountUser, String accountPassword)
	{
		dataSource = new MysqlDataSource();
		dataSource.setUrl(serverUrl);
		dataSource.setUser(accountUser);
		dataSource.setPassword(accountPassword);
	}
	
	/**
	 * Creates the singleton instance of the connection pool.
	 * 
	 * @param serverUrl The URL of the DB server
	 * @param accountUser Username
	 * @param accountPassword Password
	 * @return The singleton instance
	 */
	public static ConnectionPool createInstance(String serverUrl, String accountUser, String accountPassword)
	{
		if (instance == null)
		{
			synchronized(ConnectionPool.class)
			{ 
				instance = new ConnectionPool(serverUrl, accountUser, accountPassword);
			}
		}
		
		return instance;
	}
	
	/**
	 * Attempts to retrieve a connection from the pool.
	 * The method has a retry-logic in case of failure.
	 * 
	 * @return A DB connection
	 * @throws SQLException
	 */
	public static Connection getConnection() throws SQLException
	{
		if (instance == null)
		{
			throw new SQLException("Uninitialized pool");
		}
		
		synchronized (instance)
		{
			Connection conn = null;
			
			for (int i = 0; i < retryCount; i++)
			{
				try
				{
					conn = instance.dataSource.getConnection();
					return conn;
				}
				catch (SQLException e)
				{
					if ((i+1) >= retryCount)
						throw e;
					
					continue;	
				}
			}
			
			return conn;
		}
	}
}
